package com.zzyl.mapper;

import com.github.pagehelper.Page;
import com.zzyl.entity.Bill;
import com.zzyl.vo.BillVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;


/**
 * BillMapper
 * 账单Mapper
 */
@Mapper
public interface BillMapper {
    /**
     * 根据主键删除
     *
     * @param id 主键
     * @return 删除结果
     */
    int deleteByElderId(Long id);

    /**
     * 插入账单
     *
     * @param bill 账单实体
     * @return 插入结果
     */
    int insert(Bill bill);

    /**
     * 选择性插入账单
     *
     * @param bill 账单实体
     * @return 插入结果
     */
    int insertSelective(Bill bill);

    /**
     * 根据主键选择账单
     *
     * @param id 主键
     * @return 账单实体
     */
    Bill selectByPrimaryKey(Long id);

    /**
     * 选择账单
     *
     * @param list
     * @return 账单实体
     */
    List<Bill> selectBytradingOrderNo(@Param("list") List<Long> list);

    /**
     * 选择性更新账单
     *
     * @param bill 账单实体
     * @return 更新结果
     */
    int updateBytradingOrderNoSelective(Bill bill);


    /**
     * 选择性更新账单
     *
     * @param bill 账单实体
     * @return 更新结果
     */
    int updateByIdSelective(Bill bill);

    /**
     * 更新账单
     *
     * @param record 账单实体
     * @return 更新结果
     */
    int updateByPrimaryKey(Bill record);

    @Select("select * from bill where elder_id = #{elderId} and bill_month = #{month} and bill_type = 0 and check_in_code =#{checkInCode}")
    Bill selectByElderAndMonth(@Param("elderId") Long elderId, @Param("month") String month, @Param("checkInCode") String checkInCode);

    @Select("select * from bill where elder_id = #{elderId} and bill_type = 0 order by  bill_end_time desc limit 1")
    Bill selectLastByElder(@Param("elderId") Long elderId);

    @Select("select * from bill where elder_id = #{elderId} and bill_type = 0 order by  bill_end_time ASC limit 1")
    Bill selectFirstByElder(@Param("elderId") Long elderId);

    /**
     * 查询未付押金的账单数量
     *
     * @param elderId 老人id
     * @return 账单数量
     */
    @Select("select count(1) from bill where elder_id = #{elderId} and transaction_status = 0 and deposit_amount > 0 and bill_type = 0 ")
    Long countUnPayDepositByElderAndStatus(@Param("elderId") Long elderId);


    List<Bill> selectDepositByEldersAndStatus(@Param("elderIds") List<Long> elderIds, @Param("status") int status);

    /**
     * 查询应退 （账单）
     *
     * @param elderId
     * @param status
     * @param time
     * @return
     */
    @Select("select * from bill where elder_id = #{elderId} and bill_type = 0 and transaction_status = #{status} and bill_end_time > #{time}  and check_in_code = #{checkInCode} ORDER BY create_time DESC ")
    List<Bill> selectDueBackByElder(@Param("elderId") Long elderId, @Param("status") int status, @Param("time") LocalDateTime time, @Param("checkInCode") String checkInCode);

    /**
     * 关闭应退月度账单
     *
     * @param elderId      老人id
     * @param checkOutTime 退住时间
     */
    @Update("update bill set transaction_status=2 where elder_id = #{elderId} and bill_type = 0 and transaction_status = 1 and bill_end_time > #{checkOutTime}")
    void closeRetreatBill(@Param("elderId") Long elderId, @Param("checkOutTime") LocalDateTime checkOutTime);

    /**
     * 关闭应退的订单账单
     *
     * @param tradingOrderNoList 交易系统订单号列表
     */
    @Update("update bill set transaction_status =2 where trading_order_no in #{tradingOrderNoList}")
    void closeByTradingOrderNo(@Param("tradingOrderNoList") List<Long> tradingOrderNoList);

    /**
     * 查询应退 （订单）
     *
     * @param elderId
     * @param status
     * @return
     */
    @Select("select b.* from bill b left join `order` o  on o.trading_order_no = b.trading_order_no where b.elder_id = #{elderId} and o.status = 1 and b.bill_type = 1 and b.transaction_status = #{status} and check_in_code = #{checkInCode} ORDER BY b.create_time DESC ")
    List<Bill> selectOrderDueBackByElder(@Param("elderId") Long elderId, @Param("status") int status, @Param("checkInCode") String checkInCode);

    /**
     * 查询欠费 (月度)
     *
     * @param elderId
     * @param status
     * @param time
     * @return
     */
    @Select("select * from bill where elder_id = #{elderId} and transaction_status = #{status} and bill_type = 0 and bill_start_time < #{time} and check_in_code = #{checkInCode} ORDER BY id asc ")
    List<Bill> selectArrearageByElder(@Param("elderId") Long elderId, @Param("status") int status, @Param("time") LocalDateTime time, @Param("checkInCode") String checkInCode);

    /**
     * 退住老人的欠费月度账单变为已支付
     *
     * @param elderId      老人id
     * @param checkOutTime 退住时间
     */
    @Update("update bill set transaction_status=1 where elder_id = #{elderId} and transaction_status = 0 and bill_type = 0 and bill_start_time < #{checkOutTime}")
    void payedArrearageBill(@Param("elderId") Long elderId, @Param("checkOutTime") LocalDateTime checkOutTime);

    /**
     * 查询未缴 （订单）
     *
     * @param elderId
     * @param status
     * @return
     */
    @Select("select * from bill where elder_id = #{elderId} and transaction_status = #{status} and bill_type = 1 ORDER BY create_time DESC ")
    List<Bill> selectUnpaidByElder(@Param("elderId") Long elderId, @Param("status") int status);

    /**
     * 分页查询账单
     *
     * @param billNo      账单编号
     * @param elderName   老人姓名
     * @param elderIdCard 老人身份证号
     * @param startTime   账单月份
     * @return 分页结果
     */
    Page<BillVo> page(@Param("billNo") String billNo, @Param("elderName") String elderName, @Param("elderIdCard") String elderIdCard, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("transactionStatus") Integer transactionStatus, @Param("elderIds") List<Long> elderIds);

    /**
     * 分页查询欠费账单
     *
     * @param bedNo     床位号
     * @param elderName 老人姓名
     * @return 分页结果
     */
    Page<BillVo> arrears(@Param("bedNo") String bedNo, @Param("elderName") String elderName);

    /**
     * 批量选择性更新账单
     *
     * @param list              账单主键列表
     * @param transactionStatus 交易状态
     * @return 更新结果
     */
    int batchUpdateByTradingOrderNoSelective(@Param("list") List<Long> list, @Param("transactionStatus") int transactionStatus);

    /**
     * 批量选择性更新账单
     *
     * @param list              账单主键列表
     * @param transactionStatus 交易状态
     * @return 更新结果
     */
    int obatchUpdateByTradingOrderNoSelective(@Param("list") List<Long> list, @Param("transactionStatus") int transactionStatus, @Param("amount") BigDecimal amount);

    @Update("update bill set transaction_status = 2 where elder_id = #{elderId} and transaction_status = 0")
    void close(@Param("elderId") Long elderId);


    @Update("delete  from bill where elder_id = #{elderId} and bill_start_time > #{time}")
    void delete(@Param("elderId") Long elderId, @Param("time") LocalDateTime time);


    @Select("select * from bill where bill_no = #{relNo} and bill_type = 1 order by  bill_end_time desc limit 1")
    Bill selectByBillNo(@Param("relNo") String relNo);

    /**
     * 根据老人id和账单类型查询账单列表
     *
     * @param elderId 老人id
     * @param type    账单类型@{@link com.zzyl.enums.BillType}
     * @return 账单列表
     */
    @Select("select * from bill where elder_id=#{elderId} and bill_type =#{type}")
    List<Bill> selectByElderAndType(@Param("elderId") Long elderId, @Param("type") Integer type);

    /**
     * 查询退住时间之前未支付的账单
     *
     * @param checkInCode  入组编码
     * @param checkOutTime 退住时间
     * @return 账单列表
     */
    @Select("select * from bill where bill_type=0 and transaction_status=0 and check_in_code=#{checkInCode} and bill_start_time <=#{checkOutTime}")
    List<Bill> selectBillBeforeRetreatTime(@Param("checkInCode") String checkInCode, @Param("checkOutTime") LocalDateTime checkOutTime);

    /**
     * 更新账单
     *
     * @param bill 账单
     */
    @Update("update bill set transaction_status = #{transactionStatus},payable_amount = #{payableAmount} WHERE id = #{id}")
    void updateBill(Bill bill);

    /**
     * 查询退住时间之后的账单
     *
     * @param checkInCode  入组编码
     * @param checkOutTime 退住时间
     * @return 账单列表
     */
    @Select("select * from bill where bill_type=0 and check_in_code=#{checkInCode} and bill_start_time >#{checkOutTime}")
    List<Bill> selectBillAfterRetreatTime(@Param("checkInCode") String checkInCode, @Param("checkOutTime") LocalDateTime checkOutTime);
}

